home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Tele
/
C
/
Comet2.1.3.cpt
/
Comet
/
textedit.c
< prev
next >
Wrap
Text File
|
1991-06-25
|
25KB
|
1,103 lines
/*
Copyright Cornell University 1986. All rights are reserved.
scrinit.c contains scr_init, which initializes the screen and
create FONT bitmaps if needed (on the small-screen Mac),
and a routine to save the screen location on exit.
*/
#include <em.h>
#include <3270.h>
#include <h19.h>
#include <config.h>
#include <macdefs.h>
#include <cntldefs.h>
#include <rcodes.h>
#define SBARWIDTH 16 /* # pixels scroll bar width */
#define TEXTINSET 6 /* exactly 80 characters fit */
CursHandle textcursor; /* custom text beam */
pascal void RepAction();
pascal Boolean ClickLoop();
struct texts * textsp; /* current text edit structure for tracking */
#ifdef USETEXTWINDOWS
textwinit()
{
Rect viewrect;
Rect destrect;
Rect nullrect;
Rect sBarRect;
textcursor = GetCursor(iBeamCursor);
SetPort(emdp->textwindow);
TextFont(emdp->normfont);
TextSize(emdp->fontsize);
/* set up text edit record */
setteview(&viewrect);
settedest(&destrect);
emdp->texthand = TENew(&destrect, &viewrect);
(*emdp->texthand)->txFont = emdp->normfont;
(*emdp->texthand)->txSize = emdp->fontsize;
(*emdp->texthand)->clikLoop = (ProcPtr) ClickLoop;
nullrect.top = nullrect.left = nullrect.bottom = nullrect.right = 0;
tesetsel( (long) 0, (long) 0, emdp->texthand);
TEKey(BS, emdp->texthand);
/* fix TE cursor positioning problem--strange but true! */
/* add Hornig scrollbar */
sBarRect = emdp->textwindow->portRect;
InsetRect(&sBarRect, -1, -1 );
sBarRect.left = sBarRect.right - SBARWIDTH;
sBarRect.bottom -= (SBARWIDTH - 1); /* space for grow zone */
emdp->vBarHand = NewControl( emdp->textwindow, &sBarRect, "", (Boolean) FALSE,
0, 0, ScrollMax(emdp), scrollBarProc, 0L );
SetPort(emwindow);
}
/* set the width and fontsize of the text window. hsize is the emulator area width */
textwsize(hsize, vsize)
int hsize;
int vsize;
{
TEHandle texthand;
FontInfo finfo;
TERec * textptr;
GrafPtr oport;
Rect nviewrect;
Rect sBarRect;
GetPort(&oport);
SetPort(emdp->textwindow);
HLock(emdp->texthand);
texthand = emdp->texthand;
textptr = *texthand;
TextFont(emdp->normfont);
TextSize(emdp->fontsize);
GetFontInfo(&finfo);
textptr->fontAscent = finfo.ascent + finfo.leading;
textptr->lineHeight = textptr->fontAscent + finfo.descent;
EraseRect(&emdp->textwindow->portRect);
#ifndef SIZETEXTWINDOW
/* now we just use the given size */
hsize += SBARWIDTH + 2 * TEXTINSET; /* textwindow is a bit larger... */
vsize = (textptr->lineHeight * emdp->linecount) + (2 * TEXTINSET);
make same height as emulator */
/* was emdp->textwindow->portRect.bottom - emdp->textwindow->portRect.top, */
#endif
SizeWindow(emdp->textwindow, hsize, vsize, (Boolean) FALSE);
InvalRect(&emdp->textwindow->portRect);
/* invalidate the whole window */
textptr->txSize = (short) emdp->fontsize;
/* reset text to top */
emdp->FirstLine = 0;
/* only set certain TE vars or TE gets confused about where the text is */
#ifdef OLDDESTRECT
textptr->destRect.top = TEXTINSET;
textptr->destRect.right = thePort->portRect.right - 20;
/* reset the # of lines and the view rect */
emdp->textlines = ((thePort->portRect.bottom - TEXTINSET) / textptr->lineHeight );
textptr->viewRect.bottom = TEXTINSET + emdp->textlines * textptr->lineHeight;
/* round height of view rect to even bit multiple of font size */
textptr->viewRect.right = thePort->portRect.right - 20;
#else
textptr->destRect.top = TEXTINSET;
textptr->destRect.right = thePort->portRect.right - 22;
setteview(&nviewrect);
textptr->viewRect.bottom = nviewrect.bottom;
textptr->viewRect.right = nviewrect.right;
#endif
HideControl(emdp->vBarHand);
sBarRect = emdp->textwindow->portRect;
InsetRect(&sBarRect, -1, -1 );
sBarRect.left = sBarRect.right - SBARWIDTH;
sBarRect.bottom -= (SBARWIDTH - 1); /* space for grow zone */
MoveControl(emdp->vBarHand, sBarRect.left, sBarRect.top);
SizeControl(emdp->vBarHand, sBarRect.right - sBarRect.left,
sBarRect.bottom - sBarRect.top);
HUnlock(emdp->texthand);
#ifdef SIZETEXTWINDOW
TECalText(emdp->texthand);
InvalRect(&(*emdp->texthand)->viewRect);
#endif
textctlupd(emdp);
SelView(emdp);
ShowControl(emdp->vBarHand);
SetPort(oport);
}
textwmove(twp, hshift, vshift)
struct winds * twp;
short hshift;
short vshift;
{
Point textpoint;
GrafPtr oport;
GetPort(&oport);
SetPort(twp->textwindow);
textpoint.v = twp->textwindow->portRect.top;
textpoint.h = twp->textwindow->portRect.left;
LocalToGlobal(&textpoint);
MoveWindow(twp->textwindow, textpoint.h + hshift, textpoint.v + vshift, (Boolean) FALSE);
SetPort(oport);
}
/* append text to the emdp textwindow without disturbing selection */
textwappend(textp, length)
unsigned char * textp;
long length;
{
long selstart;
long selend;
long startlength;
register unsigned char * charp;
register unsigned char * stakep;
register long chlen;
if (! memtest(length, "to append text"))
/* out of memory */
return(-1);
selstart = (*emdp->texthand)->selStart;
selend = (*emdp->texthand)->selEnd;
startlength = (*emdp->texthand)->teLength;
if ((unsigned long) (startlength + length) > 32500L) {
short * linestart;
short linecount;
short nlines;
nlines = (*emdp->texthand)->nLines;
linestart = &(*emdp->texthand)->lineStarts[0];
linecount = 0;
while (*linestart < length) {
/* delete a page at a time */
linecount += emdp->linecount;
if (linecount >= nlines) {
error("Can't append text to Edit window");
return;
}
linestart += emdp->linecount;
}
TESetSelect((long) 0, (long) *linestart, emdp->texthand);
TEDelete(emdp->texthand);
}
tesetsel( (long) (*emdp->texthand)->teLength, (long) (*emdp->texthand)->teLength, emdp->texthand);
#ifdef NODIACRITICS
TEInsert(textp, (long) length, emdp->texthand);
#else
/* for diacritics to be represented properly, TEKey() must be called */
stakep = charp = textp;
for (chlen = 0; length--; charp++) {
if (isdiacritic[*charp]) {
/* TEKey has to be used to input diacritics properly;
must be using default font */
if (chlen) {
TEInsert(stakep, (long) chlen, emdp->texthand);
chlen = 0;
}
TEKey(*charp, emdp->texthand);
stakep = charp + 1;
}
else
chlen++;
}
if (chlen) {
/* there still remain some characters at the end */
TEInsert(stakep, (long) chlen, emdp->texthand);
}
#endif
/* reset the selection */
if (selstart != startlength)
/* only reset cursor if it was not at the end of the text */
tesetsel( (long) selstart, (long) selend, emdp->texthand);
textctlupd(emdp);
if (selstart == startlength)
/* scroll automatically if the cursor was at the end of the text */
SelView(emdp);
}
tesetsel(start, end, tehand)
long start;
long end;
TEHandle tehand;
{
(*tehand)->clikStuff = 255;
/* gruesome TE botch requires one to do this to get cursor at beginning
of line
*/
TESetSelect(start, end, tehand);
}
/* here follow routines lifted from Doug Hornig's LocalEdit.c */
/* ClickLoop is called repeatedly while the mouse button is down during editing.
* It checks if the mouse is above or below the view rectangle and performs
* automatic scrolling if it is.
*/
/* kevin: changed from pascal Boolean to long */
pascal Boolean ClickLoop()
{
Rect view;
Point mouse;
int PrevFirstLine;
RgnHandle PrevClip;
/* save regs first kevin--added from my own TE code; is this really necessary? */
view = (**keydp->texthand).viewRect; /* get the TE view rect */
PrevFirstLine = keydp->FirstLine;
GetMouse( &mouse ); /* get mouse loc in local coords */
if( mouse.v > view.bottom && keydp->FirstLine < ScrollMax(keydp) )
ScrollToLine(keydp, keydp->FirstLine + 1 ); /* below the bottom */
if( mouse.v < view.top && keydp->FirstLine > 0 )
ScrollToLine(keydp, keydp->FirstLine - 1 ); /* above the top */
if( keydp->FirstLine != PrevFirstLine ) /* have we scrolled? */
{ /* then we must draw the scroll bar */
GetClip ( PrevClip = NewRgn() ); /* because clipRgn is modified */
ClipRect ( &(**keydp->vBarHand).contrlRect ); /* during TEClick calls (like now) */
Draw1Control( keydp->vBarHand ); /* draw the scroll bar */
SetClip ( PrevClip ); /* restore the clip region */
DisposeRgn ( PrevClip );
}
return((Boolean) TRUE);
}
/* RepAction is called repeatedly by ToolBox TrackControl routine */
pascal void RepAction( CtlHand, PartCode )
ControlHandle CtlHand;
int PartCode;
{
int ScrollFac;
switch( PartCode )
{
case inUpButton:
ScrollFac = -1;
break;
case inDownButton:
ScrollFac = 1;
break;
case inPageUp:
ScrollFac = -keydp->textlines;
break;
case inPageDown:
ScrollFac = keydp->textlines;
break;
default:
return;
}
ScrollToLine(keydp, max( 0, min( keydp->FirstLine + ScrollFac, ScrollMax(keydp) ) ) );
}
/* Move Elevator is called after the scroll bar 'thumb' is moved */
MoveElevator( CtlHand )
ControlHandle CtlHand;
{
ScrollToLine(keydp, GetCtlValue( CtlHand ) );
}
/* Put theLine at the top of the screen */
ScrollToLine(twp, theLine )
struct winds * twp;
int theLine;
{
TEScroll( 0, twp->lineheight * ( twp->FirstLine - theLine ), twp->texthand );
SetCtlValue( twp->vBarHand, twp->FirstLine = theLine );
}
/* Make sure the selection range is in view */
SelView(twp)
struct winds * twp;
{
register int NewFirst; /* line selection starts on */
/* Return the line number that the selection range starts on.
* Range is 0 through nLines-1.
*/
static int PrevCur = 0;
int *FrstLine;
register int *LastLine, *CheckLine;
register int SelLoc;
int NumLines;
/* kevin: folded in CurLine() routine */
if( ( NumLines = (**twp->texthand).nLines - 1 ) < 0 ) {
NewFirst = PrevCur = 0; /* nLines is sometimes zero */
}
else {
SelLoc = (**twp->texthand).selStart;
FrstLine = (**twp->texthand).lineStarts;
LastLine = FrstLine + NumLines;
CheckLine = FrstLine + min( PrevCur, NumLines );
while( *CheckLine < SelLoc && CheckLine < LastLine )
CheckLine++; /* check lineStarts after previous curline */
while( *CheckLine > SelLoc )
CheckLine--; /* then check lineStarts before it */
NewFirst = PrevCur = CheckLine - FrstLine;
}
if( NewFirst < twp->FirstLine ) {
/* kevin: replaced ScrollToLine( NewFirst ); which uses keydp */
ScrollToLine(twp, NewFirst );
}
else if( ( NewFirst -= (twp->textlines - 1) ) > twp->FirstLine ) {
ScrollToLine(twp, NewFirst );
}
}
/* ScrollMax is used to calculate the maximum scroll bar setting */
int ScrollMax(twp)
struct winds * twp;
{
return( max( twp->FirstLine, (**twp->texthand).nLines - (twp->textlines) ) );
}
int min( v1, v2 )
register int v1, v2;
{
return( v1 < v2 ? v1 : v2 );
}
int max( v1, v2 )
register int v1, v2;
{
return( v1 > v2 ? v1 : v2 );
}
/* textwunwrap attempts to convert the text in TextHand from -mainframe- format
* to -TextEdit- format. That means changing the returns at the end of lines
* that should be wrapped into spaces.
*/
textwunwrap(twp)
struct winds * twp;
{
register char prev, this, next, *cPtr;
register int theLen;
register int charcount = 0;
register int selstart = (*twp->texthand)->selStart;
register int selend = (*twp->texthand)->selEnd;
GrafPtr oport;
GetPort(&oport);
if ( ( theLen = (*twp->texthand)->teLength ) == 0 )
return; /* zero length text */
SetPort(twp->textwindow);
if (selstart == selend) {
/* if no selection, convert the whole TE text */
selstart = 0;
selend = theLen;
}
cPtr = *(*twp->texthand)->hText;
prev = ' '; /* load initial characters */
this = *cPtr++;
next = *cPtr;
while( ++charcount < theLen ) /* loop though the whole text */
{
/* only convert the selection range */
if (charcount < selstart) {
++cPtr;
continue;
}
if (charcount > selend)
break;
if ( this == '\r' ) {
/* a return, check to see if it should be replaced with a space */
if ( ! ( prev == '\r'
|| next == ' '
|| next == TAB
|| next == '\r'
)
) {
/* there are non-space characters around it, replace it with a space */
*(cPtr - 1) = ' ';
}
}
prev = this; /* shift the chars over */
this = next;
next = *++cPtr;
}
TECalText(twp->texthand);
InvalRect(&(*twp->texthand)->viewRect);
textctlupd(twp);
SelView(twp);
SetPort(oport);
}
/* textwwrap performs the opposite function that textwunwrap does. It puts return
* characters at the end of each line that is wrapped by TextEdit.
*/
textwwrap(twp)
struct winds * twp;
{
register int *lStart = (*twp->texthand)->lineStarts;
register char *theText = *(*twp->texthand)->hText;
register int lCount = (*twp->texthand)->nLines;
register short crpos;
register int selstart = (*twp->texthand)->selStart;
register int selend = (*twp->texthand)->selEnd;
int textlen;
textlen = (*twp->texthand)->teLength;
if (textlen == 0)
return; /* zero length text */
if (selstart == selend) {
/* if no selection, convert the whole TE text */
selstart = 0;
selend = textlen;
}
while( --lCount > 0) {
/* only convert the selection range */
crpos = *++lStart;
if (crpos < selstart)
continue;
if (crpos > selend)
break;
theText[ crpos - 1 ] = '\r'; /* put a return at each EOL */
}
/* no need to update, because the appearance is unchanged */
}
/* end of Hornig routines */
textctlupd(twp)
struct winds * twp;
{
SetCtlMax( twp->vBarHand, ScrollMax(twp) ); /* make sure scroll bar max is correct */
SetCtlValue( twp->vBarHand, twp->FirstLine ); /* and the thumb is in the right place */
}
/* cut text from a text window */
textwcut(twp)
struct winds * twp;
{
twp->textscrapped = TRUE;
SelView(twp); /* guarantee FirstLine won't change */
TECut(twp->texthand);
textctlupd(twp);
}
/* cut text from a text window */
textwclear(twp)
struct winds * twp;
{
SelView(twp); /* guarantee FirstLine won't change */
TEDelete(twp->texthand);
textctlupd(twp);
}
/* copy text from a text window */
textwcopy(twp)
struct winds * twp;
{
long len;
twp->textscrapped = TRUE;
len = (*twp->texthand)->selEnd - (*twp->texthand)->selStart;
if (memtest(len, copyerr)) {
TECopy(twp->texthand);
}
}
/* paste text into a text window */
textwpaste(twp)
struct winds * twp;
{
long len;
len = TEScrLen -
((*twp->texthand)->selEnd - (*twp->texthand)->selStart);
if (len < 0 || memtest(len, copyerr)) {
/* might be smaller than before... */
SelView(twp); /* guarantee FirstLine won't change */
TEPaste(twp->texthand);
textctlupd(twp);
SelView(twp);
}
}
#define FILECOMPAT
#ifdef FILECOMPAT
/* all Aztec C file routines blow the resource fork away, and must
be changed to use Mac routines */
/* if the filename is the same as the session name, save the text
buffer in the file before an upload takes place
*/
textupedit(filename)
char * filename;
{
FILE *textfp;
int writecount;
char filebuffer[514];
unsigned short textlength;
char macfile[256];
if (!emdp->editload)
return(-1);
GetWTitle(emdp->textwindow, &macfile[0]);
ptoc(&macfile[0]);
if (strcmp(filename, &macfile[0]) == 0) {
/* the filename matches the text window name "SESSIONNAME.edit", go for it */
/* save the text buffer in the file */
if (emdp->editupwrap)
textwwrap(emdp); /* wrap text with Carriage Returns first */
HLock((*emdp->texthand)->hText);
textlength = (*emdp->texthand)->teLength;
textfp = fopen(filename, "w");
if (textfp != NULL) {
writecount = fwrite(*(*emdp->texthand)->hText, 1, textlength, textfp);
if (writecount != textlength) {
error("Can't save whole text into upload file");
}
fclose(textfp);
}
else
error("Can't open upload file to save text");
HUnlock((*emdp->texthand)->hText);
}
return(0);
}
/* if the filename is the same as the session name, load it into the text
buffer
*/
textdownedit(filename)
char * filename;
{
char macfile[256];
if (!emdp->editload)
return(-1);
GetWTitle(emdp->textwindow, &macfile[0]);
ptoc(&macfile[0]);
if (strcmp(filename, &macfile[0]) == 0) {
/* the filename matches "SESSIONNAME.edit", go for it */
#ifdef DOWNDELETE
/* we probably don't want to automatically delete the current text */
/* first delete the current text */
tesetsel( (long) 0, (long) (*emdp->texthand)->teLength, emdp->texthand);
TEDelete(emdp->texthand);
textctlupd(emdp);
SelView(emdp);
#endif
textwload(filename);
if (emdp->editdownwrap)
textwunwrap(emdp);
/* eliminate most Carriage Returns in text */
}
return(0);
}
/* append a file to the .edit window */
textwload(filename)
char *filename;
{
FILE *textfp;
int readcount;
long readtotal;
char filebuffer[514];
textfp = fopen(filename, "r");
if (textfp != NULL) {
readtotal = 0;
while (TRUE) {
readcount = fread(&filebuffer[0], 1, 512, textfp);
readtotal += readcount;
if (readcount == 0) {
/* we've read the whole file or can't read any more */
break;
}
textwappend(&filebuffer[0], (long) readcount);
}
fclose(textfp);
if (readtotal > 32500)
error("Couldn't read the whole file into .edit (> 32,500 characters)");
putaction(RSLT_EMC, EM_EDIT); /* bring up the edit window */
}
else
error("Can't load file into text window");
}
#else
/* are file compatibility routines in place ? */
textupedit()
{
}
textdownedit()
{
}
#endif
#else
/* not USETEXTWINDOWS */
textwinit()
{
}
textwsize()
{
}
/* no text windows, do nothing */
textupedit()
{
}
textdownedit()
{
}
/* when text windows are disabled, append operations go into the clipboard */
textwappend(textp, length)
char * textp;
long length;
{
puttextscrap(textp, length);
}
textctlupd(twp)
struct winds * twp;
{
}
textwcopy(twp)
struct winds * twp;
{
}
textwpaste(twp)
struct winds * twp;
{
}
textwcut(twp)
struct winds * twp;
{
}
textwwrap(twp)
struct winds * twp;
{
}
textwunwrap(twp)
struct winds * twp;
{
}
tesetsel()
{
}
#endif
/* set the selection to the end of the text and jump to it */
textwgotoend(twp)
struct winds * twp;
{
tesetsel( (long) (*twp->texthand)->teLength,
(long) (*twp->texthand)->teLength,
twp->texthand);
ScrollToLine(twp, ScrollMax(twp));
}
#ifdef USETEXTWINDOWS
/* append the keymap to the text window */
#define XTEXT 500
#define NEG (-1)
char kxappstart[] = "\r\rKey Macro list:\r";
char kxappend[] = "\r\rEnd of Key Macro list\r\r";
keyxappend()
{
TEHandle texthand = keydp->texthand;
long length;
unsigned char thetext[XTEXT + 6];
EventRecord anevent;
struct keyxlist * keyxp;
long keyxid;
short dkeycode, modifiers;
unsigned char * actptr;
unsigned char * textend;
struct token * keyact;
int count;
getcontext(keydp); /* textwappend() uses emdp */
strcpy(&thetext[0], "\r\t");
/* a carriage return & tab starts off the line */
textwappend(&kxappstart[0], (long) strlen(&kxappstart[0]));
for (keyxp = keydp->keyxhead; keyxp != NULL; keyxp = keyxp->nextkey) {
keyxid = ((struct keyactlist *) (*keyxp->hkeyact))->keyid;
modifiers = ((keyxid >> 16) & 0xffff);
dkeycode = (keyxid & 0xffff) >> 8;
/* now dump the codes for it */
count = keyxp->actlen;
keyact = &((struct keyactlist *) (*keyxp->hkeyact))->act[0];
actptr = &thetext[2];
for (textend = &thetext[2] + XTEXT; count--; keyact++) {
if ( (length = actdecode(actptr, textend, keyact, FALSE)) == NEG)
/* error decoding--should alert that at end? */
break;
else
actptr += length;
}
length = actptr - &thetext[2];
*actptr++ = ' ';
/* make sure diacritic has something nice to sit on */
*actptr++ = TAB;
/* add a tab for formatting */
/* give the key a name */
namekey(actptr, dkeycode, modifiers);
actptr += strlen(actptr);
if (length == 1) {
/* if the code was just a single character, give decimal equivalent also */
*actptr++ = TAB;
*actptr++ = '\\';
dectrans(actptr, thetext[2]);
actptr += 3; /* 3 characters just added... */
}
length = actptr - &thetext[0];
if (! memtest(length, "to dump key macros"))
/* out of memory */
break;
textwappend(&thetext[0], (long) length);
/* starts with 0 to insert a CR */
}
textwappend(&kxappend[0], (long) strlen(&kxappend[0]));
}
#endif
/*
* display text in a text window; both are taken from resource file, with the
* assumption the id number is the same for both
*/
helptextwindow(resid)
{
long length;
Handle thetext;
thetext = GetResource('TEXT', (short) resid);
if (thetext == NULL)
return(-1);
getcontext(keydp); /* textwappend uses emdp */
HLock(thetext);
length = GetHandleSize(thetext);
textwappend(*thetext + 4, (long) (length - 4));
/* TEXT types have 4 bytes of length in them */
HUnlock(thetext);
}
/* set the textedit view rectangle,
assumes
portRect.top == 0
textedit lineHeight == fontsize
*/
setteview(viewrect)
Rect * viewrect;
{
FontInfo finfo;
int lineheight;
GetFontInfo(&finfo);
lineheight = finfo.ascent + finfo.descent + finfo.leading;
emdp->textlines =
((thePort->portRect.bottom - thePort->portRect.top - TEXTINSET - 4)
/ lineheight );
viewrect->top = TEXTINSET;
viewrect->left = thePort->portRect.left;
viewrect->bottom = viewrect->top + emdp->textlines * lineheight;
/* round height of view rect to even bit multiple of font size */
viewrect->right = thePort->portRect.right - 16;
}
/* set the textedit destination rectangle which sets wrap boundaries */
settedest(destrect)
Rect * destrect;
{
destrect->top = TEXTINSET;
destrect->left = TEXTINSET;
destrect->bottom = thePort->portRect.bottom - thePort->portRect.top;
destrect->right = thePort->portRect.right - 20 - (2 * emdp->hoffset);
}
#ifdef USETEXTWINDFIND
/* this routine finds a string in a TextEdit record */
#define FINDMAX 1024
#define FORWARD 1
#define BACKWARD 2
char fstring[FINDMAX];
findstring(texthand, foundat, dir)
TEHandle texthand;
long * foundat;
int dir;
{
char * text;
int start;
int end;
int length;
int count;
int offset;
int skip;
count = strlen(&fstring[0]); /* TODO should be eliminated */
text = *(*texthand)->hText;
start = (*texthand)->selStart;
end = (*texthand)->selEnd;
length = (*texthand)->teLength;
skip = (start == end) ? 0 : 1;
if (dir == FORWARD) {
if ((offset = match(fstring, text + start + skip, text + length, dir)) >= 0) {
*foundat = start + skip + offset;
return(count);
}
/* Not found on first try; wrap and search to initial position */
if ((offset = match(fstring, text, text + start + count, dir)) >= 0) {
*foundat = offset;
return(count);
}
}
else {
if ((offset = match(fstring, text, text + start, dir)) >= 0) {
*foundat = offset;
return(count);
}
/* Not found on first try; wrap and search to initial position */
if ((offset = match(fstring, text + start, text + length, dir)) >= 0) {
*foundat = start + offset;
return(count);
}
}
/* no match */
return(0);
}
/* find a match, returning the offset from the start value */
match(string, startp, endp, dir)
char * string;
register char * startp;
register char * endp;
int dir;
{
register int count;
register int total;
register char * strp;
register char * fstrp;
count = 0;
total = strlen(string);
if (dir == FORWARD) {
/* search to end */
strp = startp;
for (fstrp = string; strp < endp; strp++) {
if (*fstrp == *strp) {
/* contents equal, try next match */
if (++count == total) {
/* search succeeds, return offset from start */
return(strp - startp - count + 1);
}
fstrp++;
continue;
}
else {
/* a number of matches have failed */
fstrp = string;
strp -= count;
count = 0;
}
}
}
else {
/* search backwards */
strp = endp;
fstrp = string + total - 1;
/* on last character in string */
while (--strp >= startp) {
if (*fstrp == *strp) {
/* contents equal, try next match */
--fstrp;
if (++count == total) {
/* search succeeds, return offset from start */
return(strp - startp);
}
continue;
}
else {
/* a number of matches have failed to pan out */
fstrp = string + total - 1;
strp += count;
count = 0;
}
}
}
return(-1);
}
textncopy(source, destination, len, maxlen)
char * source;
char * destination;
int len;
register int maxlen; /* maximum length in destination */
{
register char * srcp;
register char * destp;
register char * endpos;
register int count;
count = 0;
srcp = source;
destp = destination;
for (endpos = srcp + len; srcp < endpos; destp++, srcp++) {
*destp = *srcp;
if (++count >= maxlen) {
/* we can't move the whole thing */
*destp = '\0';
return(-1);
}
}
*destp = '\0';
}
#endif